using System;
using System.Xml;
using System.Configuration;

using System.Collections;
using System.Collections.Specialized;

namespace CodePlex.Diagnostics
{
    /// <summary>
    /// Provides runtime support for reading provider configuration sections.
    /// </summary>
    internal sealed class ProviderConfiguration
    {
        #region ProviderConfiguration Private Fields

        private string m_defaultExceptionProvider;
        private string m_defaultLoggingProvider;

        private Hashtable m_exceptionProviders;
        private Hashtable m_loggingProviders;

        #endregion

        #region public ProviderConfiguration(XmlNode section)

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ProviderConfiguration"/> class.    
        /// </summary>
        /// <param name="section"></param>
        public ProviderConfiguration(XmlNode section)
        {
            m_exceptionProviders = new Hashtable();
            m_loggingProviders = new Hashtable();

            XmlNode exceptionProviders = section.SelectSingleNode("exceptions");

            this.DefaultExceptionProvider = exceptionProviders.Attributes["defaultProvider"].Value;

            foreach (XmlNode provider in exceptionProviders.ChildNodes)
            {
                if (provider.Name == "providers")
                {
                    GetProviders(provider, this.ExceptionProviders);
                }
            }

            XmlNode loggingProviders = section.SelectSingleNode("logging");

            this.DefaultLoggingProvider = loggingProviders.Attributes["defaultProvider"].Value;

            foreach (XmlNode provider in loggingProviders.ChildNodes)
            {
                if (provider.Name == "providers")
                {
                    GetProviders(provider, this.LoggingProviders);
                }
            }
        }

        #endregion

        #region public static ProviderConfiguration GetConfiguration(string section)

        /// <summary>
        /// Gets the <see cref="T:CodePlex.Diagnostics.ProviderConfiguration"/> for the supplied section.
        /// </summary>
        /// <returns>The <see cref="T:CodePlex.Diagnostics.ProviderConfiguration"/> for the supplied section.</returns>
        public static ProviderConfiguration GetConfiguration()
        {
            ProviderConfiguration configuration = ConfigurationManager.GetSection(@"codePlex.diagnostics") as ProviderConfiguration;

            return configuration;
        }

        #endregion

        #region public string DefaultExceptionProvider

        /// <summary>
        /// Gets or sets the default exception provider.
        /// </summary>
        /// <value>The default exception provider.</value>
        public string DefaultExceptionProvider
        {
            get
            {
                return m_defaultExceptionProvider;
            }
            private set
            {
                m_defaultExceptionProvider = value;
            }
        }

        #endregion

        #region public string DefaultLoggingProvider

        /// <summary>
        /// Gets or sets the default logging provider.
        /// </summary>
        /// <value>The default logging provider.</value>
        public string DefaultLoggingProvider
        {
            get
            {
                return m_defaultLoggingProvider;
            }
            private set
            {
                m_defaultLoggingProvider = value;
            }
        }

        #endregion

        #region public Hashtable ExceptionProviders

        /// <summary>
        /// Gets a <see cref="T:System.Collections.Hashtable"/> containing the configured exception providers.
        /// </summary>
        /// <value>A <see cref="T:System.Collections.Hashtable"/> containing the configured exception providers.</value>
        public Hashtable ExceptionProviders
        {
            get
            {
                return m_exceptionProviders;
            }
        }

        #endregion

        #region public Hashtable LoggingProviders

        /// <summary>
        /// Gets a <see cref="T:System.Collections.Hashtable"/> containing the configured logging providers.
        /// </summary>
        /// <value>A <see cref="T:System.Collections.Hashtable"/> containing the configured logging providers.</value>
        public Hashtable LoggingProviders
        {
            get
            {
                return m_loggingProviders;
            }
        }

        #endregion

        #region private static void GetProviders(XmlNode node)

        /// <summary>
        /// Gets the providers within the specified <see cref="T:System.Xml.XmlNode"/>.
        /// </summary>
        /// <param name="node">The <see cref="T:System.Xml.XmlNode"/> containing zero or more providers.</param>
        /// <param name="providers">The <see cref="T:System.Collections.Hashtable"/> within which the providers should be inserted.</param>
        private static void GetProviders(XmlNode node, Hashtable providers)
        {
            foreach (XmlNode childNode in node.ChildNodes)
            {
                switch (childNode.Name)
                {
                    case "add":
                        providers.Add(childNode.Attributes["name"].Value, new Provider(childNode.Attributes));
                        break;

                    case "remove":
                        providers.Remove(childNode.Attributes["name"].Value);
                        break;

                    case "clear":
                        providers.Clear();
                        break;
                }
            }
        }

        #endregion
    }
}
